package com.zl.cms.auth;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * User: zl email:c3tc3tc3t@126.com Date: 14-3-1 Time: 下午9:51
 */
public class AuthUtil {
  /**
   * 初始化系统的所有角色所访问的功能信息
   * 
   * @return
   */
  public static Map<String, Set<String>> initAuth(String pname) {
    Map<String, Set<String>> auths = new HashMap<>();
    String[] ps = getClassByPackage(pname);
    for (String p : ps) {
      String pc = pname + "." + p.substring(0, p.lastIndexOf(".class"));

      try {
        Class clz = Class.forName(pc);
        if (!clz.isAnnotationPresent(AuthClass.class)) {
          continue;
        }
        Method[] ms = clz.getDeclaredMethods();
        /**
         * 便利method来判断每个method上面是否有相应的AuthMethod 如果存在直接将这个方法存储到auths中,如果不存在就不存储,
		 * 不存储就意味着该方法只能由超级管理员访问
         */
        for (Method m : ms) {

          if (!m.isAnnotationPresent(AuthMethod.class)) {
            continue;
          }
          // 如果存在获取这个annotation
          AuthMethod am = m.getAnnotation(AuthMethod.class);

          String roles = am.role();
			//可能一个action被多个角色访问，使用逗号分隔
			String[] aroles = roles.split(",");
			for(String role : aroles) {
				Set<String> actions = auths.get(role);
				if (null == actions) {
					actions = new HashSet<>();
					auths.put(role, actions);
				}
				actions.add(pc+"."+m.getName());
			}



        }
        // 获取每个类中的方法，以此来确定哪些角色可以访问哪些方法
      } catch (ClassNotFoundException e) {
        // e.printStackTrace();
      }
    }
    return auths;
  }

  /**
   * 根据包获得所有的类
   * 
   * @param pname
   * @return
   */
  private static String[] getClassByPackage(String pname) {
    String pr = pname.replace(".", "/");
    String pp = AuthUtil.class.getClassLoader().getResource(pr).getPath();
    File file = new File(pp);
    String[] fs = file.list(new FilenameFilter() {
      @Override
      public boolean accept(File dir, String name) {
        if (name.endsWith(".class")) return true;
        return false;
      }
    });
    return fs;
  }


}
